<template>
  <div class="course-section">
    <el-card>
      <div slot="header">
        课程名称
      </div>
      <el-tree
        :data="sectionList"
        :props="defaultProps"
        draggable
        :allow-drop="handleAllowDrop"
        @node-drop="handleNodeDrop"
        v-loading="isLoading">
        <!-- 设置插槽，并通过插槽接收组件暴露的数据 -->
        <div class="inner" slot-scope="{ node, data }">
          <!-- 设置内容 -->
          <span>{{ node.label }}</span>
          <!-- 设置后续按钮结构 -->
          <!-- section 结构 -->
          <span v-if="data.sectionName" class="actions">
            <el-button>编辑</el-button>
            <el-button>添加课时</el-button>
            <el-button>状态</el-button>
          </span>
          <!-- lesson 结构 -->
          <span v-else class="actions">
            <el-button>编辑</el-button>
            <el-button
              type="success"
              @click="$router.push({
                name: 'course-video',
                params: {
                  courseId
                }
              })"
            >上传视频</el-button>
            <el-button>状态</el-button>
          </span>
        </div>
      </el-tree>
    </el-card>
  </div>
</template>

<script>
import { getSectionAndLesson, saveOrUpdateSection, saveOrUpdateLesson } from '@/services/course'

export default {
  name: 'CourseSection',
  props: {
    courseId: {
      type: [String, Number],
      required: true
    }
  },
  data () {
    return {
      sectionList: [],
      defaultProps: {
        children: 'lessonDTOS',
        label (data) {
          return data.sectionName || data.theme
        }
      },
      isLoading: false
    }
  },
  methods: {
    async loadSectionList () {
      const { data } = await getSectionAndLesson(this.courseId)
      if (data.code === '000000') {
        console.log(data)
        this.sectionList = data.data
      }
    },
    // 拖拽操作判断
    handleAllowDrop (draggingNode, dropNode, type) {
      // 1. 不能有放入内部的操作，但例如将章节1拖拽到章节2的课时1之前时，type 为 prev，需要进一步处理
      // 2. 所有课时都具有 sectionId，通过下面的条件，限制章节不能移动到课时前后，也不能将章节的课时移动到其他章节
      return type !== 'inner' && draggingNode.data.sectionId === dropNode.data.sectionId
    },
    async handleNodeDrop (draggingNode, dropNode, tyoe, event) {
      this.isLoading = true
      // 1. 无论是章节还是课时, dropNode 都有parent(draggingNode.parent 总为 null), 内部有childNodes
      // - dropNode.parent.childNodes 可获取拖拽项所在列表的所有数据
      // - 遍历操作
      // 4. 由于是批量请求，可以使用 Promise.all() 便于进行统一操作
      //   - 将 map 返回的，由 Axios 调用返回的 Promise 对象组成的数组，传入到 Promise.all() 中
      //   - 设置 async await 并进行 try..catch 处理
      try {
        await Promise.all(dropNode.parent.childNodes.map((item, index) => {
          // 2. 对章节与课时进行分别处理
          //   - 除了 draggingNode.data.sectionId 外，draggingNode.lessonDTOS 也可以判断
          if (draggingNode.data.lessonDTOS) {
            // 章节操作
            return saveOrUpdateSection({
              id: item.data.id,
              // 按现在的索引顺序给当前级别列表设置排序序号
              orderNum: index
            })
          } else {
            // 课时操作（同上）
            return saveOrUpdateLesson({
              id: item.data.id,
              // 按现在的索引顺序给当前级别列表设置排序序号
              orderNum: index
            })
          }
        }))
        this.$message.success('数据更新成功')
      } catch (err) {
        this.$message.success('数据更新失败', err)
      }
      this.isLoading = false
    }
  },
  created () {
    this.loadSectionList()
  }
}
</script>

<style lang="scss" scoped>
.inner {
  // 浏览器观察到父元素设置了 flex，所以当前元素 flex: 1 占满一行
  flex: 1;
  // 内部元素希望左右分开，所以给当前元素设置 flex
  display: flex;
  justify-content: space-between;
  align-items: center;
  // 其他样式美化
  padding: 10px;
  border-bottom: 1px solid #ebeef5;
}

// 当前行具有类名 .el-tree-node__content 设置了固定高度 26px, 这里要改为 auto 自适应
// 由于为 Tree 组件内的元素，需要设置样式穿透
::v-deep .el-tree-node__content {
  height: auto;
}
</style>
